• LwIP在逻辑上分为4个层次:链路层、网络层、传输层、应用层

  • LwIP协议栈内部使用了一个名为netif的网络接口结构来描述各种网络设备

  • LwIP为每个接口分配一个netif结构,用这个结构来描述每种接口的特性,如接口IP地址、接口状态等,同时在该结构中为每个接口注册对应的操作函数,如数据包输入函数、输出函数等。内核将所有网络接口的netif结构组织在一个叫做netif_list的链表上,当有IP数据包需要发送时,IP层会根据数据包的目的IP地址,在netif_list链表中选择一个最合适的网络接口,并调用其注册的数据包发送函数将数据包发送出去;当网卡接收到数据包时,其注册的数据包输入函数也会被调用,完成将数据包交给IP层的任务。

  • 数据结构

  • netif.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #define NETIF_MAX_HWADDR_LEN 6U // 网络接口最大物理地址长度,这里定义为以太网网卡MAC地址的长度6
    // 下面几个宏为网络接口属性、状态相关的宏,主要用于描述netif中flags字段的各位
    #define NETIF_FLAG_UP 0x01U //网络接口是否已被上层使能
    #define NETIF_FLAG_BROADCAST 0x02U //网络接口是否支持广播
    #define NETIF_FLAG_POINTTOPOINT 0x04U //网络接口是否属于点到点连接
    #define NETIF_FLAG_DHCP 0x08U //网络接口是否支持DHCP功能
    #define NETIF_FLAG_LINK_UP 0x10U //网络接口的底层链路是否已经使能
    #define NETIF_FLAG_ETHARP 0x20U //网络接口是否支持ARP功能
    #define NETIF_FLAG_IGMP 0x40U //网络接口是否支持IGMP
    struct netif {
    struct netif* next; //指向下一个netif结构,在构成链表netif_list时使用
    struct ip_addr ip_addr; //网络接口的IP地址
    struct ip_addr netmask; //子网掩码
    struct ip_addr gw; //网关地址
    err_t (*input)(strcut pbuf* p, strut netif* inp); //该函数向IP层输入数据包
    err_t (*output)(struct netif* netif, struct pbuf* p, struct ip_addr* ipaddr); // 该函数发送IP包
    err_t (*linkoutput)(struct netif* netif, struct pbuf* p); // 该函数实现底层数据包发送
    void* state; //该字段用户可以自由设置,例如用于指向一些底层设备相关的信息
    u16_t mtu; //该接口允许的最大数据包长度
    u8_t hwaddr_len; //该接口物理地址长度
    u8_t hwaddr[NETIF_MAX_HWARRR_LEN]; //该接口的物理地址
    u8_t flags; //该接口的状态、属性字段
    char name[2]; //该接口的名字
    u8_t num; //接口的编号
    //在接口自输入使能或者有环回接口的情况下,下面的字段用于描述接口发送给自己的数据包
    struct pbuf* loop_first; //指向发送给自己的数据包的第一个pbuf
    struct pbuf* loop_last; //指向发送给自己的数据包的最后一个pbuf
    };